
/*******************************************************************************
 * Copyleft (c) 2021 Kcode
 *
 * @file    s3c2440_dma.c
 * @brief   ASOC框架下的platform部分，对s3c2440控制芯片的dma接口进行设置，
 *          参考sound\soc\samsung\dma.c
 *
 * @note    核心结构体snd_soc_platform_driver
 * @author  K
 * @version 0.0.1
 * @date    2021-08-07
 * @license MulanPSL-1.0
 *
 * 文件修改历史：
 * <时间>       | <版本>    | <作者>  | <描述>
 * 2021-08-07   | v0.0.1    | Kcode   | s3c2440控制芯片的dma接口的设置
 * -----------------------------------------------------------------------------
 ******************************************************************************/

/*!
 * 控制芯片的iis传输数据时dma属性设置
 */
static const struct snd_pcm_hardware s3c_2440_dma_hardware = {
	.info			= SNDRV_PCM_INFO_INTERLEAVED |
				    SNDRV_PCM_INFO_BLOCK_TRANSFER |
				    SNDRV_PCM_INFO_MMAP |
				    SNDRV_PCM_INFO_MMAP_VALID |
				    SNDRV_PCM_INFO_PAUSE |
				    SNDRV_PCM_INFO_RESUME,  /**< 数据存放格式、排列方式 */
	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
				    SNDRV_PCM_FMTBIT_U16_LE |
				    SNDRV_PCM_FMTBIT_U8 |
				    SNDRV_PCM_FMTBIT_S8,    /**< 音频数据格式 */

    /* 通道数 */
	.channels_min		= 2,
	.channels_max		= 2,

    /* 传输音频数据的信息 */
	.buffer_bytes_max	= 128*1024,
	.period_bytes_min	= PAGE_SIZE,
	.period_bytes_max	= PAGE_SIZE*2,
	.periods_min		= 2,
	.periods_max		= 128,
	.fifo_size		= 32,
};

/*!
 * @brief dma接口属性、数据设置
 * @return int 0
 */
static int s3c2440_dma_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;

    /* 设置属性 */
	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
	snd_soc_set_runtime_hwparams(substream, &s3c_2440_dma_hardware);

	return 0;
}

/*!
 * @brief 根据params参数设置s3c2440控制芯片上的dma接口的寄存器
 * @return int 0
 */
static int s3c2440_dma_hw_params(struct snd_pcm_substream *substream,
	                                            struct snd_pcm_hw_params *params)
{

	return 0;
}

static struct snd_pcm_ops s3c2440_dma_ops = {
    .open = s3c2440_dma_open,
	.hw_params	= s3c2440_dma_hw_params,
};

/*!
 * 核心结构体snd_soc_platform_driver
 */
static struct snd_soc_platform_driver s3c2440_dma_platform = {
	.ops		= &s3c2440_dma_ops,
	//.pcm_new	= dma_new,
	//.pcm_free	= dma_free_dma_buffers,
};

/*!
 * @brief 关闭设备的函数，必须得有，否则程序编译报错
 * @return void
 */
static void s3c2440_dma_dev_release(struct device *dev)
{}

/*!
 * 分配注册一个名为s3c2440_iis_dev的平台设备
 */
static struct platform_device s3c2440_dma_dev = {
    .name    = "s3c2440-dma",
    .id      = -1,
    .device  = {
        .release = s3c2440_dma_dev_release,
    },
};

/*!
 * @brief  根据名字，连接到对应的平台驱动与设备时所调用的函数
 * @return int
 */
static int s3c2440_dma_probe(struct platform_device *pdev)
{    
    return snd_soc_register_platform(&pdev->dev, &s3c2440_dma_platform);
}

/*!
 * @brief 关闭平台驱动的函数，必须得有，否则程序编译报错
 * @return int
 */
static int s3c2440_dma_remove(struct platform_device *pdev)
{
    return snd_soc_unregister_platform(&pdev->dev);
}

/*!
 * 分配注册一个名为s3c2440_dma_dev的平台驱动
 */
struct platform_driver s3c2440_dma_drv = {
    .probe   = s3c2440_dma_probe,
    .remove  = s3c2440_dma_remove,
    .driver  = {
        .name = "s3c2440-dma",
    },
};

/*!
  * @brief 入口函数
  * @return int 0：注册成功，1：注册失败
  */
 static int s3c2440_dma_init(void)
 {
     int ret = 0;
 
     ret = platform_device_register(&s3c2440_dma_dev);
     if (ret) {
         printk("Can not register platform s3c2440_dma_dev!\n");
         goto fail;
     }
 
     ret = platform_driver_register(&s3c2440_dma_drv);
     if (ret) {
         printk("Can not register platform s3c2440_dma_drv!\n");
         platform_device_unregister(&s3c2440_dma_dev);
         goto fail;
     }
 
 fail:    
     return ret;
 }
 
 /*!
  * @brief 出口函数
  * @return int，
  */
 static void s3c2440_dma_exit(void)
 {
     platform_driver_unregister(&s3c2440_dma_drv);
     platform_device_unregister(&s3c2440_dma_dev);
 }
  
  /* 修饰 */
  module_init(s3c2440_dma_init);
  module_exit(s3c2440_dma_exit);
  
  /* 协议 */
  MODULE_LICENSE("GPL");

